﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace OmniKits.Core
{
    using NullGuard;

    public class SecureBufferWriter : TextWriter
    {
#pragma warning disable 1591

        public override Encoding Encoding => Defaults.UnicodeEncoding;

        public SecureBufferWriter(IList<char> buffer)
        {
            _Buffer = buffer;
        }

        private IList<char> _Buffer;
        private int _Position = 0;
        public int Position
        {
            get { return _Position; }
            set { _Position = value; }
        }

        public override void Write(char value)
        {
            _Buffer[_Position++] = value;
        }
    }

    public class SecureStreamWriter : TextWriter
    {
#if PCL
        private static Encoding StaticEncoding = Encoding.UTF8;
#else
        private static Encoding StaticEncoding = Encoding.GetEncoding(Encoding.ASCII.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
#endif
        public override Encoding Encoding => StaticEncoding;

        private Stream _Stream;
        private bool _CloseStream = false;
        public SecureStreamWriter(Stream stream)
            : this(stream, true)
        { }
        public SecureStreamWriter(Stream stream, bool closeStream)
        {
            _Stream = stream;
            _CloseStream = closeStream;
        }

        public override void Write(char value)
        {
            _Stream.WriteByte(checked((byte)value));
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_CloseStream)
                    _Stream.Dispose();
            }

            base.Dispose(disposing);
        }
    }

    public class SecureFakeWriter : TextWriter
    {
        public override Encoding Encoding => Defaults.UnicodeEncoding;

        public override void Write([AllowNull]string value)
        {
            throw new NotSupportedException();
        }

        private int _Count = 0;
        public int Count { get { return _Count; } }

        public override void Write(char value)
        {
            _Count++;
        }
    }

    public class SecureFakeStream : Stream
    {
        public override bool CanRead => false;

        public override bool CanSeek => false;

        public override bool CanWrite => true;

        public override void Flush() { }

        private long _Count = 0;
        public override long Length=>_Count;

        public override long Position
        {
            get
            {
                return _Count;
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (offset + count > buffer.Length)
                throw new ArgumentException();
            _Count += count;
        }
    }
}
